Trò chơi đua xe động vật trong UNITY Engine
- HorizontalScrollSnap.cs
- Layout /
- AnimalRacing /
- Scripts /
- Assets /
- project /
2 /// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-1945602
3 /// Updated by ddreaper - removed dependency on a custom ScrollRect script. Now implements drag interfaces and standard Scroll Rect.
4
5 using UnityEngine.EventSystems;
6
7 namespace UnityEngine.UI.Extensions
8 {
9
10 [RequireComponent(typeof(ScrollRect))]
11 [AddComponentMenu("Layout/Extensions/Horizontal Scroll Snap")]
12 public class HorizontalScrollSnap : ScrollSnapBase, IEndDragHandler
13 {
14 void Start()
15 {
16 _isVertical = false;
17 _childAnchorPoint = new Vector2(0, 0.5f);
18 _currentPage = StartingScreen;
19 UpdateLayout();
20 }
21
22 void Update()
23 {
24 if (!_lerp && _scroll_rect.velocity == Vector2.zero)
25 {
26 if (!_settled && !_pointerDown)
27 {
28 if (!IsRectSettledOnaPage(_screensContainer.localPosition))
29 {
30 ScrollToClosestElement();
31 }
32 }
33 return;
34 }
35 else if (_lerp)
36 {
37 _screensContainer.localPosition = Vector3.Lerp(_screensContainer.localPosition, _lerp_target, transitionSpeed * Time.deltaTime);
38 if (Vector3.Distance(_screensContainer.localPosition, _lerp_target) < 0.1f)
39 {
40 _lerp = false;
41 EndScreenChange();
42 }
43 }
44
45 CurrentPage = GetPageforPosition(_screensContainer.localPosition);
46
47 //If the container is moving check if it needs to settle on a page
48 if (!_pointerDown)
49 {
50 if (_scroll_rect.velocity.x > 0.01 || _scroll_rect.velocity.x < 0.01)
51 {
52 //if the pointer is released and is moving slower than the threshold, then just land on a page
53 if (IsRectMovingSlowerThanThreshold(0))
54 {
55 ScrollToClosestElement();
56 }
57 }
58 }
59 }
60
61 private bool IsRectMovingSlowerThanThreshold(float startingSpeed)
62 {
63 return (_scroll_rect.velocity.x > startingSpeed && _scroll_rect.velocity.x < SwipeVelocityThreshold) ||
64 (_scroll_rect.velocity.x < startingSpeed && _scroll_rect.velocity.x > -SwipeVelocityThreshold);
65 }
66
67 private void DistributePages()
68 {
69 _screens = _screensContainer.childCount;
70 _scroll_rect.horizontalNormalizedPosition = 0;
71
72 int _offset = 0;
73 float _dimension = 0;
74 Rect panelDimensions = gameObject.GetComponent<RectTransform>().rect;
75 float currentXPosition = 0;
76 var pageStepValue = _childSize = (int)panelDimensions.width * ((PageStep == 0) ? 3 : PageStep);
77
78
79 for (int i = 0; i < _screensContainer.transform.childCount; i++)
80 {
81 RectTransform child = _screensContainer.transform.GetChild(i).gameObject.GetComponent<RectTransform>();
82 currentXPosition = _offset + (int)(i * pageStepValue);
83 child.sizeDelta = new Vector2(panelDimensions.width, panelDimensions.height);
84 child.anchoredPosition = new Vector2(currentXPosition, 0f);
85 child.anchorMin = child.anchorMax = child.pivot = _childAnchorPoint;
86 }
87
88 _dimension = currentXPosition + _offset * -1;
89
90 _screensContainer.GetComponent<RectTransform>().offsetMax = new Vector2(_dimension, 0f);
91 }
92
93 /// <summary>
94 /// Add a new child to this Scroll Snap and recalculate it's children
95 /// </summary>
96 /// <param name="GO">GameObject to add to the ScrollSnap</param>
97 public void AddChild(GameObject GO)
98 {
99 AddChild(GO, false);
100 }
101
102 /// <summary>
103 /// Add a new child to this Scroll Snap and recalculate it's children
104 /// </summary>
105 /// <param name="GO">GameObject to add to the ScrollSnap</param>
106 /// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
107 public void AddChild(GameObject GO, bool WorldPositionStays)
108 {
109 _scroll_rect.horizontalNormalizedPosition = 0;
110 GO.transform.SetParent(_screensContainer, WorldPositionStays);
111 DistributePages();
112 if (MaskArea) UpdateVisible();
113
114 SetScrollContainerPosition();
115 }
116
117 /// <summary>
118 /// Remove a new child to this Scroll Snap and recalculate it's children
119 /// *Note, this is an index address (0-x)
120 /// </summary>
121 /// <param name="index"></param>
122 /// <param name="ChildRemoved"></param>
123 public void RemoveChild(int index, out GameObject ChildRemoved)
124 {
125 ChildRemoved = null;
126 if (index < 0 || index > _screensContainer.childCount)
127 {
128 return;
129 }
130 _scroll_rect.horizontalNormalizedPosition = 0;
131
132 Transform child = _screensContainer.transform.GetChild(index);
133 child.SetParent(null);
134 ChildRemoved = child.gameObject;
135
136 DistributePages();
137 if (MaskArea) UpdateVisible();
138
139 if (_currentPage > _screens - 1)
140 {
141 CurrentPage = _screens - 1;
142 }
143
144 SetScrollContainerPosition();
145 }
146
147 /// <summary>
148 /// Remove all children from this ScrollSnap
149 /// </summary>
150 /// <param name="ChildrenRemoved"></param>
151 public void RemoveAllChildren(out GameObject[] ChildrenRemoved)
152 {
153 var _screenCount = _screensContainer.childCount;
154 ChildrenRemoved = new GameObject[_screenCount];
155
156 for (int i = _screenCount - 1; i >= 0; i--)
157 {
158 ChildrenRemoved[i] = _screensContainer.GetChild(i).gameObject;
159 ChildrenRemoved[i].transform.SetParent(null);
160 }
161
162 _scroll_rect.horizontalNormalizedPosition = 0;
163 CurrentPage = 0;
164 InitialiseChildObjectsFromScene();
165 DistributePages();
166 if (MaskArea) UpdateVisible();
167 }
168
169 private void SetScrollContainerPosition()
170 {
171 _scrollStartPosition = _screensContainer.localPosition.x;
172 _scroll_rect.horizontalNormalizedPosition = (float)(_currentPage) / (_screens - 1);
173 }
174
175 /// <summary>
176 /// used for changing / updating between screen resolutions
177 /// </summary>
178 public void UpdateLayout()
179 {
180 _lerp = false;
181 DistributePages();
182 if (MaskArea) UpdateVisible();
183 SetScrollContainerPosition();
184 OnCurrentScreenChange(_currentPage);
185 }
186
187 private void OnRectTransformDimensionsChange()
188 {
189 if (_childAnchorPoint != Vector2.zero)
190 {
191 UpdateLayout();
192 }
193 }
194
195 #region Interfaces
196 /// <summary>
197 /// Release screen to swipe
198 /// </summary>
199 /// <param name="eventData"></param>
200 public void OnEndDrag(PointerEventData eventData)
201 {
202 _pointerDown = false;
203
204 if (_scroll_rect.horizontal)
205 {
206 if (UseFastSwipe)
207 {
208 //If using fastswipe - then a swipe does page next / previous
209 if ((_scroll_rect.velocity.x > 0 &&_scroll_rect.velocity.x > FastSwipeThreshold) ||
210 _scroll_rect.velocity.x < 0 && _scroll_rect.velocity.x < -FastSwipeThreshold)
211 {
212 _scroll_rect.velocity = Vector3.zero;
213 if (_startPosition.x - _screensContainer.localPosition.x > 0)
214 {
215 NextScreen();
216 }
217 else
218 {
219 PreviousScreen();
220 }
221 }
222 else
223 {
224 ScrollToClosestElement();
225 }
226 }
227 }
228 }
229 #endregion
230 }
231 }
Credit BinaryX
Sourced from - http:forum.unity3d.comthreadsscripts-useful-4-6-scripts-collection.264161page-2#post-1945602
Updated by ddreaper - removed dependency on a custom ScrollRect script. Now implements drag interfaces and standard Scroll Rect.
If the container is moving check if it needs to settle on a page
if the pointer is released and is moving slower than the threshold, then just land on a page
Add a new child to this Scroll Snap and recalculate it's children
GameObject to add to the ScrollSnap
Add a new child to this Scroll Snap and recalculate it's children
GameObject to add to the ScrollSnap
Should the world position be updated to it's parent transform?
Remove a new child to this Scroll Snap and recalculate it's children
*Note, this is an index address (0-x)
Remove all children from this ScrollSnap
used for changing updating between screen resolutions
Release screen to swipe
If using fastswipe - then a swipe does page next previous